15. Constructor Functions

Declaring Constructor Functions

Both Python and C++ have constructor functions. Constructor functions define what happens when you instantiate an object.

Python Constructor

These are the functions that define what happens when an object is instantiated. In Python, the syntax is:

def __init__(self, variable1, variable2, ..., variablen):
    self.variable1 = variable1
    self.variable2 = variable2
    self.variablen = variablen

C++ Constructor Declaration

In C++, you declare a constructor like this:

Classname (datatype variable1, datatype variable2, …, datatype variablen);

You can also simultaneously declare a default constructor function, which implies the function has no inputs:

Classname ();

This default constructor function is used when you instantiate an object without providing values for the variables. To be more concrete, you will initialize a Matrix variable with a two-dimensional vector. If you do not provide a two-dimensional vector, you could initialize your Matrix variable with a default vector. This second case is what the empty constructor function is for.

The Gaussian constructor declarations looked like this:

class Gaussian
{
    private:
        ...

    public:
        ...
        Gaussian ();
        Gaussian (float, float);

   ....
};

Whether or not you use a default constructor function will depend on your particular application and use-case. For example, if an object always has the same initial values, then it would make sense to have a default constructor function.

Defining Constructor Functions

Once you've declared your constructor functions, you need to actually define them in a .cpp file.

The constructor function definitions have the following syntax:

// empty constructor function syntax
Classname::ClassName() {

    constructor function definition
}

// constructor function syntax
Classname::ClassName(datatype variable1, datatype variable2, …, datatype variablen) {

    constructor function definition

}

You can see how this was done for the Gaussian class:

Gaussian::Gaussian() {
    mu = 0;
    sigma2 = 1; 
}

Gaussian::Gaussian (float average, float sigma) {
    mu = average;
    sigma2 = sigma;
}

Note that constructor functions do not return anything. They merely initialize class variables. You might also be wondering how the function definitions can access mu and sigma2 if those were private variables. Remember that private variables can be accessed from within the class code itself but not from outside the class.

Initializing with Default Values

In both Python and C++, you can use default values in your construction functions. In Python, the syntax is:

def __init__(self, variable1 = default1, variable2 = default2, ..., variablen = defaultn):
    self.variable1 = variable1
    self.variable2 = variable2
    self.variablen = variablen

You can also get this functionality in C++ although the syntax might not be what you'd expect; you actually define default values in the .h file function definition. Here is a trivial example for an addition Class that holds two integers and outputs their sum.

Here is the header file add.h:

class Add
{
    public:
        int a;
        int b;

        Add(int, int second = 17);

        int addition();
};

and then here are the definitions in add.cpp:

#include  "add.h"

Add::Add(int first, int second) {

    a = first;
    b = second;
}

int Add::addition() {
    return a + b;
}

Notice that the default value was declared in the header file. Now, if you only specify one value when instantiating an add object, variable b will have a default value of 17:

#include <iostream>

#include  "add.h"

int main() {

    Add adder(5);
    std::cout << adder.addition() << std::endl;
    return 0;

}

The above code outputs 22.

Declare and Define Matrix Class Constructors

Now it's your turn. Fill out the TODO sections in the matrix.h and matrix.cpp files.

Start Quiz:

#include <iostream>
#include <vector>
#include "matrix.h"

int main () {
    
    // TODO: Nothing to do here
    
    return 0;
}
#include "matrix.h"

/* TODO: Define the default constructor. Remember the syntax is
**      Classname::ClassName() {
**    
**          initialize variables
**    
**       }
**
**
**      You need to initialize the grid variable to a default value such as
**      a 4x4 matrix with all zeros.
**
**      Then initialize the rows variable, and the cols variable using the
**      vector size method. For example myvector.size() will give the size of
**      a vector. For a 2-dimensional vector, myvector.size() would be the
**      number of rows in a matrix.
**
*/

/* TODO: Define a constructor that receives a 2-Dimensional vector
**       and assigns the vector to the grid variable. 
**       
**      Remember the syntax is
**      Classname::ClassName(datatype inputvariablename) {
**    
**          classvariable = inputvariablename
**    
**       }
**
**      Then initialize the rows variable, and the cols variable exactly
**      as you did for the default constructor.
**
*/
#include <vector>

class Matrix 
{

        private:

            std::vector< std::vector<float> > grid;
            std::vector<float>::size_type rows;
            std::vector<float>::size_type cols;
            
        public:
        
        /* 
        ** TODO: Declare  constructor functions
        ** For the matrix class, you will need two constructor functions.
        ** 1. An empty constructor function
        ** 2. A constructor function that accepts a 2-dimensional vector
        */
        
};

Solution matrix.h

#include <vector>

class Matrix 
{

        private:

            std::vector< std::vector<float> > grid;
            std::vector<float>::size_type rows;
            std::vector<float>::size_type cols;

        public:

            // constructor function declarations
            Matrix ();
            Matrix (std::vector< std::vector<float> >);
};

Solution matrix.cpp

#include "matrix.h"

Matrix::Matrix() {
    std::vector <std:: vector <float> > initial_grid (10, std::vector <float>(5, 0.5));
    grid = initial_grid;
    rows = initial_grid.size();
    cols = initial_grid[0].size();

}

Matrix::Matrix(std::vector <std:: vector <float> > initial_grid) {
    grid = initial_grid;
    rows = initial_grid.size();
    cols = initial_grid[0].size();
}